import fetch, { Request, type RequestInit } from "node-fetch";
import type { HttpResponse } from "@common/http-types.ts";

export { type RequestInit };

const defaultUa = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36";

export interface RequestOptions extends RequestInit {
  timeout?: number;
}

export function request(url: string, options?: RequestOptions) {
  const { timeout, ...init } = options || {};
  init.signal = init.signal || (timeout ? AbortSignal.timeout(timeout) : undefined);
  return fetch(
    new Request(url, {
      method: init.method || "GET",
      ...init,
      headers: {
        "User-Agent": defaultUa,
        ...init.headers,
      },
    }),
  );
}

export function get(url: string, options?: RequestOptions) {
  return request(url, options);
}

export function getText(url: string, options?: RequestOptions): Promise<HttpResponse<string>> {
  return get(url, options).then(async res => ({
    data: await res.text(),
  }));
}

export function getJson<T = any>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {
  return get(url, options).then(async res => ({
    data: (await res.json()) as T,
  }));
}

export function post(url: string, options?: RequestOptions) {
  return request(url, { ...options, method: "POST" });
}

export function postText(url: string, body: any, options?: RequestOptions): Promise<HttpResponse<string>> {
  return post(url, { ...options, body: JSON.stringify(body) }).then(async res => ({
    data: await res.text(),
  }));
}

export function postJson<T = any>(url: string, body: any, options?: RequestOptions): Promise<HttpResponse<T>> {
  return post(url, { ...options, body: JSON.stringify(body) }).then(async res => ({
    data: (await res.json()) as T,
  }));
}
